#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>     
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include "common.h"

ssize_t mt_read(int fd, void *buf, size_t nbytes, int spins) {
	if(nbytes == 0)
		return 0;
	
	mt_thread_t th;
	int fullread = 0, inc;
	uint32_t vp = mt_get_vcpu();
	if(vp == -1) 
		return -1;
	
	if(nbytes == 0)
		return 0;
	
	th = mt_thread_self();
	
	while(nbytes > 0) {
		inc = read(fd, ((char*)buf) + fullread, nbytes);
		
		if(inc > 0) {
			fullread += inc;
			nbytes -= inc;
			continue;
		}
		
		if(inc == 0)
			return fullread;
		
		if(inc == -1) 
			if(errno == EAGAIN) {
			th->state =  _MT_MT_IO_WAIT;
			th->waitValue = 2;
			if(spins-- == 0) {
				return fullread;
			}
			
			{_MT_SWITCH_CONTEXT(th, vp);}
			continue;
			} else {
				return -1;
			}
	}

	return fullread;
}

ssize_t mt_write(int fd, void *buf, size_t nbytes, int spins) {
	if(nbytes == 0)
		return 0;	
	
	mt_thread_t th;
	int fullwrite = 0, outc;

	uint32_t vp = mt_get_vcpu();
	if(vp == -1)
		return -1;
	
	th = mt_thread_self();
	
	while(nbytes > 0) {
		outc = write(fd, ((char*)buf) + fullwrite, nbytes);
		
		if(outc > 0) {
			fullwrite += outc;
			nbytes -= outc;
			continue;
		}
		
		if(outc == 0)
			return fullwrite;
		
		if(outc == -1) 
			if(errno == EAGAIN) {
				if(!--spins)
					return fullwrite;
				th->state =  _MT_MT_IO_WAIT;
				th->waitValue = 1;
				{_MT_SWITCH_CONTEXT(th, vp);}
			continue;
			} else {
				return -1;
			}
	}

	return fullwrite;
}

